package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import com.atguigu.tingshu.album.client.TrackInfoFeignClient;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.factory.StrategyFactory;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.user.strategy.ItemTypeStrategy;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.joda.time.LocalTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitService rabbitService;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;

    @Autowired
    private TrackInfoFeignClient trackInfoFeignClient;

    @Autowired
    private UserVipServiceMapper userVipServiceMapper;

    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Autowired
    private StrategyFactory factory;

    @Override
    public void updateVipExpireStatus() {
        //  调用mapper 层方法.
        try {
            Long count = userInfoMapper.updateVipExpireStatus();
        } catch (Exception e) {
            throw new GuiguException( 500,"更新用户vip状态失败！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void savePaidRecord(UserPaidRecordVo userPaidRecordVo) {
        //  调用工厂获取到策略对象
        ItemTypeStrategy strategy = factory.getStrategy(userPaidRecordVo.getItemType());
        //  调用具体策略实现类
        strategy.savePaidRecord(userPaidRecordVo);
        //  根据购买类型向    表中添加数据！
        //  判断
        //        if (userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_ALBUM)) {
        //            //  购买专辑 user_paid_album
        //            LambdaQueryWrapper<UserPaidAlbum> wrapper = new LambdaQueryWrapper<>();
        //            wrapper.eq(UserPaidAlbum::getAlbumId, userPaidRecordVo.getItemIdList().get(0)).eq(UserPaidAlbum::getUserId, userPaidRecordVo.getUserId());
        //            UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(wrapper);
        //            //  判断用户是否购买过
        //            if (null != userPaidAlbum) {
        //                return;
        //            }
        //            //  创建对象
        //            userPaidAlbum = new UserPaidAlbum();
        //            userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
        //            userPaidAlbum.setAlbumId(userPaidRecordVo.getItemIdList().get(0));
        //            userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
        //            userPaidAlbumMapper.insert(userPaidAlbum);
        //
        //        } else if (userPaidRecordVo.getItemType().equals(SystemConstant.ORDER_ITEM_TYPE_TRACK)) {
        //            //  购买声音 user_paid_track
        //            //  select * from user_paid_track where user_id = ? and track_id in();
        //            LambdaQueryWrapper<UserPaidTrack> wrapper = new LambdaQueryWrapper<>();
        //            wrapper.eq(UserPaidTrack::getUserId, userPaidRecordVo.getUserId()).in(UserPaidTrack::getTrackId, userPaidRecordVo.getItemIdList());
        //            List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(wrapper);
        //            if (userPaidTrackList.size() > 0) return;
        //            //  根据声音Id获取到声音对象；
        //            //  userPaidRecordVo.getItemIdList().get(0) 获取第一个声音Id
        //            Result<TrackInfo> trackInfoResult = trackInfoFeignClient.getTrackInfo(userPaidRecordVo.getItemIdList().get(0));
        //            Assert.notNull(trackInfoResult.getData(), "声音信息不存在！");
        //            TrackInfo trackInfo = trackInfoResult.getData();
        //            Assert.notNull(trackInfo, "声音所属专辑不存在！");
        //            //  否则就添加:
        //            for (Long trackId : userPaidRecordVo.getItemIdList()) {
        //                //  创建用户购买声音对象
        //                UserPaidTrack userPaidTrack = new UserPaidTrack();
        //                userPaidTrack.setUserId(userPaidRecordVo.getUserId());
        //                userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
        //                userPaidTrack.setTrackId(trackId);
        //                userPaidTrack.setAlbumId(trackInfo.getAlbumId());
        //                //  保存购买声音记录.
        //                userPaidTrackMapper.insert(userPaidTrack);
        //            }
        //
        //        } else {
        //            //  购买vip user_vip_service 或 user_info 更新is_vip 字段为 1
        //            //  创建对象
        //            UserVipService userVipService = new UserVipService();
        //            //  赋值：
        //            userVipService.setUserId(userPaidRecordVo.getUserId());
        //            userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
        //            userVipService.setStartTime(new Date());
        //            //  1. 先知道购买的多长时间
        //            Long itemId = userPaidRecordVo.getItemIdList().get(0); // vip_service_config.id
        //            VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(itemId);
        //            //  用户购买的时长
        //            Integer serviceMonth = vipServiceConfig.getServiceMonth();
        //            //  2.用户当前的身份
        //            UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
        //            //  创建一个过期时间对象;
        //            Date exprieTime = new Date();
        //            //  3.  判断是否需要续期的问题 当前这个用户是vip ，并且未过期要续期：user_info.vip_expire_time + serviceMonth;
        //            if (userInfo.getIsVip() == 1 && userInfo.getVipExpireTime().after(new Date())){
        //                //  要续期：
        //                LocalDateTime localDateTime = new LocalDateTime(userInfo.getVipExpireTime());
        //                //  System.out.println(localDateTime.plusMonths(serviceMonth).toDate());
        //                //  续期时间
        //                exprieTime = localDateTime.plusMonths(serviceMonth).toDate();
        //            } else {
        //                //  头一次开vip
        //                exprieTime = new LocalDateTime().plusMonths(serviceMonth).toDate();
        //            }
        //            //  不是续期的情况；当前系统时间加购买时长
        //            //  Date exprieTime = new LocalDateTime().plusMonths(serviceMonth).toDate();
        //            userVipService.setExpireTime(exprieTime);
        //            //  设置vip过期时间：
        //            userVipServiceMapper.insert(userVipService);
        //            //  手动编写一个运行时异常
        ////            int i = 1/0;
        //            //  续期或头一次购买；都应该将用户信息更新为vip用户 is_vip=1; vip_expire_time;
        //            userInfo.setIsVip(1);
        //            userInfo.setVipExpireTime(exprieTime);
        //            //  更新用户信息;
        //            this.userInfoMapper.updateById(userInfo);
        //        }
    }

    @Override
    public List<Long> findUserPaidTrackList(Long albumId, Long userId) {
        //  select track_id from user_paid_track where album_id = ? and user_id = ?
        List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId).select(UserPaidTrack::getTrackId));
        //  获取到声音Id 列表
        List<Long> list = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        //  返回数据
        return list;
    }

    @Override
    public Boolean isPaidAlbum(Long userId, Long albumId) {
        //  user_paid_album select * from user_paid_album where album_id = ? and user_id = ? ; 不为空说明已经购买过！返回true;
        return userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getAlbumId, albumId).eq(UserPaidAlbum::getUserId, userId)) != null;
    }

    /**
     * 判断用户是否购买过专辑或声音
     *
     * @param albumId
     * @param userId
     * @param trackIdList
     * @return key=trackId value=0/1 0:未购买 1:已购买
     */
    @Override
    public Map<Long, Integer> userIsPaidTrack(Long albumId, Long userId, List<Long> trackIdList) {
        //  创建map 集合
        //  Map<Long, Integer> map = new HashMap<>();
        //  用户是否购买过专辑; user_paid_album
        //  select * from user_paid_album where album_id = ? and user_id = ?
        UserPaidAlbum userPaidAlbum = userPaidAlbumMapper.selectOne(new LambdaQueryWrapper<UserPaidAlbum>().eq(UserPaidAlbum::getAlbumId, albumId).eq(UserPaidAlbum::getUserId, userId));
        //  判断是否存在 购买过专辑
        if (null != userPaidAlbum) {
            //            for (Long trackId : trackIdList) {
            //                map.put(trackId, 1);
            //            }
            Map<Long, Integer> map = trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, k -> 1));
            return map;
        }
        //  用户是否购买过声音；user_paid_track
        //  select  * from user_paid_track where user_id = 25 and album_id = 1451 and track_id in (48796,48797);
        //  查询用户购买的声音集合列表
        List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(new LambdaQueryWrapper<UserPaidTrack>().eq(UserPaidTrack::getAlbumId, albumId).eq(UserPaidTrack::getUserId, userId).in(UserPaidTrack::getTrackId, trackIdList));
        List<Long> trackIdPaidList = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        //  当前专辑对应的所有需要付费的声音列表 trackIdList
        if (CollectionUtils.isEmpty(trackIdPaidList)) {
            //  返回map
            return trackIdList.stream().collect(Collectors.toMap(trackId -> trackId, k -> 0));
        } else {
            //  声明一个map集合
            Map<Long, Integer> map = new HashMap<>();
            for (Long trackId : trackIdList) {
                //  判断
                if (trackIdPaidList.contains(trackId)) {
                    map.put(trackId, 1);
                } else {
                    map.put(trackId, 0);
                }
            }
            return map;
        }
    }

    @Override
    public void updateUser(Long userId, UserInfoVo userInfoVo) {
        //  创建userInfo 对象
        UserInfo userInfo = new UserInfo();
        userInfo.setId(userId);
        userInfo.setNickname(userInfoVo.getNickname());
        userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());
        //  调用mapper方法.
        this.userInfoMapper.updateById(userInfo);
    }

    /**
     * 根据用户ID获取用户信息的视图对象
     *
     * @param userId 用户ID，用于标识哪个用户的信息将被检索
     * @return 返回UserInfoVo对象，其中包含了用户的相关信息
     */
    @Override
    public UserInfoVo getUserInfo(Long userId) {
        // 通过用户ID获取UserInfo对象
        UserInfo userInfo = this.getById(userId);
        // 创建UserInfoVo对象，用于返回用户信息
        UserInfoVo userInfoVo = new UserInfoVo();
        // 将UserInfo对象的属性复制到UserInfoVo对象
        BeanUtils.copyProperties(userInfo, userInfoVo);
        // 返回包含用户信息的UserInfoVo对象
        return userInfoVo;
    }

    @Override
    public Map<String, Object> wxLogin(String code) {
        //	调用api 方法获取openid。
        String openid = null;
        try {
            openid = wxMaService.jsCode2SessionInfo(code).getOpenid();
        } catch (WxErrorException e) {
            throw new RuntimeException(e);
        }
        //	通过openid查询用户信息表
        UserInfo userInfo = userInfoMapper.selectOne(new LambdaQueryWrapper<UserInfo>().eq(UserInfo::getWxOpenId, openid));
        //	判断用户信息是否存在
        if (null == userInfo) {
            //	创建用户对象
            userInfo = new UserInfo();
            //	赋值
            userInfo.setWxOpenId(openid);
            userInfo.setNickname("听友:" + System.currentTimeMillis());
            userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
            this.userInfoMapper.insert(userInfo);
            //  初始化账户信息：第一种方式：openFeign 远程调用！ 第二种方式：mq 发送的消息由消费者来决定！
            this.rabbitService.sendMessage(MqConst.EXCHANGE_USER, MqConst.ROUTING_USER_REGISTER, userInfo.getId());
        }
        //	声明一个token
        String token = UUID.randomUUID().toString().replaceAll("-", "");
        //  将用户信息存储到缓存中。
        String userLoginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
        this.redisTemplate.opsForValue().set(userLoginKey, userInfo, RedisConstant.USER_LOGIN_KEY_TIMEOUT, TimeUnit.SECONDS);
        //  创建map对象
        Map<String, Object> map = new HashMap<>();
        map.put("token", token);
        //  返回数据
        return map;
    }
}
